]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
shell-global: try to resync the pointer state after grabs
authorDan Winship <danw@gnome.org>
Wed, 19 Jan 2011 15:29:50 +0000 (10:29 -0500)
committerDan Winship <danw@gnome.org>
Mon, 21 Mar 2011 18:56:53 +0000 (14:56 -0400)
If the pointer moves on or off the stage while another process has a
grab, we will lose track of it. One example of this is that if you use
a popup menu from a message tray trayicon, the tray will stay up after
the menu goes away, because the shell never saw the pointer leave it.

Add a new method shell_global_sync_pointer() that causes clutter to
recheck what actor is under the pointer and generate leave/enter
events if appropriate.

Of course, we can't actually tell for sure when another process has a
grab, so we need a heuristic of when to call this. Currently we call
it from Chrome._windowsRestacked(), which is not really the right
thing at all, but does fix the menu-from-trayicon case...

https://bugzilla.gnome.org/show_bug.cgi?id=630842

js/ui/chrome.js
src/shell-global.c
src/shell-global.h

index 32b8f04f426f1903b2f59ffdeaab5d7dfd2264a1..27779fcf32f817a73d2a7adf5670dab2582cd6c8 100644 (file)
@@ -335,6 +335,11 @@ Chrome.prototype = {
             this._updateVisibility();
             this._queueUpdateRegions();
         }
+
+        // Figure out where the pointer is in case we lost track of
+        // it during a grab. (In particular, if a trayicon popup menu
+        // is dismissed, see if we need to close the message tray.)
+        global.sync_pointer();
     },
 
     _updateRegions: function() {
index 32836cba5070b022889cadccae579c797a7e15a9..44f4aff668ff359119f212d5840b2331ba238902 100644 (file)
@@ -1490,6 +1490,48 @@ shell_global_get_pointer (ShellGlobal         *global,
   *mods = raw_mods & GDK_MODIFIER_MASK;
 }
 
+/**
+ * shell_global_sync_pointer:
+ * @global: the #ShellGlobal
+ *
+ * Ensures that clutter is aware of the current pointer position,
+ * causing enter and leave events to be emitted if the pointer moved
+ * behind our back (ie, during a pointer grab).
+ */
+void
+shell_global_sync_pointer (ShellGlobal *global)
+{
+  int x, y;
+  GdkModifierType mods;
+  ClutterMotionEvent event;
+
+  gdk_display_get_pointer (gdk_display_get_default (), NULL, &x, &y, &mods);
+
+  event.type = CLUTTER_MOTION;
+  event.time = shell_global_get_current_time (global);
+  event.flags = 0;
+  /* This is wrong: we should be setting event.stage to NULL if the
+   * pointer is not inside the bounds of the stage given the current
+   * stage_input_mode. For our current purposes however, this works.
+   */
+  event.stage = CLUTTER_STAGE (meta_plugin_get_stage (global->plugin));
+  event.x = x;
+  event.y = y;
+  event.modifier_state = mods;
+  event.axes = NULL;
+  event.device = clutter_device_manager_get_core_device (clutter_device_manager_get_default (),
+                                                         CLUTTER_POINTER_DEVICE);
+
+  /* Leaving event.source NULL will force clutter to look it up, which
+   * will generate enter/leave events as a side effect, if they are
+   * needed. We need a better way to do this though... see
+   * http://bugzilla.clutter-project.org/show_bug.cgi?id=2615.
+   */
+  event.source = NULL;
+
+  clutter_event_put ((ClutterEvent *)&event);
+}
+
 /**
  * shell_get_event_state:
  * @event: a #ClutterEvent
index 40f9a8f9bacef5dcd4d253f8f618d71cb30a9c4d..cda10e455a3ab885dcf92cae7891c7e130be05f8 100644 (file)
@@ -103,10 +103,11 @@ MetaRectangle *shell_global_get_primary_monitor (ShellGlobal  *global);
 int            shell_global_get_primary_monitor_index (ShellGlobal  *global);
 MetaRectangle *shell_global_get_focus_monitor   (ShellGlobal  *global);
 
-void shell_global_get_pointer (ShellGlobal         *global,
-                               int                 *x,
-                               int                 *y,
-                               ClutterModifierType *mods);
+void shell_global_get_pointer  (ShellGlobal         *global,
+                                int                 *x,
+                                int                 *y,
+                                ClutterModifierType *mods);
+void shell_global_sync_pointer (ShellGlobal         *global);
 
 GSettings *shell_global_get_settings (ShellGlobal *global);